/* MachinePlayer.java */

package player;

/**
 *  An implementation of an automatic Network player.  Keeps track of moves
 *  made by both players.  Can select a move for itself.
 *  @field color is the color of the MachinePlayer object.
 */

public class MachinePlayer extends Player {

	int color;
	int opponentColor;
	int searchDepth = 2; 
	GameBoard gb; 

	// Creates a machine player with the given color.  Color is either 0 (black)
	// or 1 (white).  (White has the first move.)
	public MachinePlayer(int color) {
		this.color = color;
		if (color == GameBoard.WHITE) {
			opponentColor = GameBoard.BLACK;
		} else {
			opponentColor = GameBoard.WHITE;
		}
		gb = new GameBoard(this.color);
	}

	// Creates a machine player with the given color and search depth.  Color is
	// either 0 (black) or 1 (white).  (White has the first move.)
	public MachinePlayer(int color, int searchDepth) {
		this(color);
		this.searchDepth = searchDepth;
	}


	// Returns a new move by "this" player.  Internally records the move (updates
	// the internal game board) as a move by "this" player.
	public Move chooseMove() {
		MoveAndScore bestMove = gb.minimax(color,-100000,100000,0,searchDepth,new MoveAndScore());
		gb.doMove(bestMove.move,color);
		return bestMove.move;
	} 

	// If the Move m is legal, records the move as a move by the opponent
	// (updates the internal game board) and returns true.  If the move is
	// illegal, returns false without modifying the internal state of "this"
	// player.  This method allows your opponents to inform you of their moves.
	public boolean opponentMove(Move m) {
		if (gb.isValidMove(m,opponentColor) == false) {
			return false;
		}
		gb.doMove(m,opponentColor);
		return true;
	}

	// If the Move m is legal, records the move as a move by "this" player
	// (updates the internal game board) and returns true.  If the move is
	// illegal, returns false without modifying the internal state of "this"
	// player.  This method is used to help set up "Network problems" for your
	// player to solve.
	public boolean forceMove(Move m) {
		if (gb.isValidMove(m, this.color) == false) {
			return false;
		}
		gb.doMove(m, this.color);
		return true;
	}


	/*** for testing *****/
	public static void main (String[] args) {

		final int CORNER = -2;
		final int EMPTY = -1;
		final int BLACK = 0;
		final int WHITE = 1;


		System.out.println("\n== Testing opponentMove() ==\t Total Tests: 3 ");

		GameBoard gb1 = new GameBoard(BLACK);
		MachinePlayer mp1 = new MachinePlayer(BLACK);
		gb1.board[3][0].color = BLACK;	// Set up a test board.
		gb1.board[2][1].color = WHITE;
		gb1.board[5][2].color = BLACK;
		gb1.board[5][3].color = WHITE;
		gb1.board[2][4].color = BLACK;
		gb1.board[6][5].color = WHITE;
		gb1.board[1][6].color = BLACK;
		gb1.board[4][7].color = WHITE;
		System.out.println("Gameboard gb1: \n" + gb1);
		Move myMove = new Move(3,0);
		boolean t = !mp1.opponentMove(myMove);
		gb1.verify(t, "Test Failed. Move is illegal due to already existing chip.");
		myMove = new Move (1,0);
		t = !mp1.opponentMove(myMove);
		gb1.verify (t, "Test Failed. Move is illegal due to clustering.");
		myMove = new Move (6,1);
		t = mp1.opponentMove (myMove);
		gb1.verify (t, "Test Failed. Should have been able to move.");

		System.out.println("\n== Testing forceMove() ==\t Total Tests: 4");

		GameBoard gb2 = new GameBoard(BLACK);
		MachinePlayer mp2 = new MachinePlayer(BLACK);
		// mp2.forceMove(new Move(4, 0));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(1, 1));
		// mp2.forceMove(new Move(2, 1));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(6, 1));
		// mp2.forceMove(new Move(3, 2));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(2, 2));
		// mp2.forceMove(new Move(5, 2));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(4, 2));
		// mp2.forceMove(new Move(5, 3));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(1, 4));
		// mp2.forceMove(new Move(3, 5));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(6, 3));
		// mp2.forceMove(new Move(5, 5));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(2, 5));
		// mp2.forceMove(new Move(2, 4));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(4, 5));
		// mp2.forceMove(new Move(6, 6));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(0, 6));
		//mp2.forceMove(new Move(1, 7));
		mp2.forceMove(mp2.chooseMove());
		mp2.opponentMove(new Move(5, 6));
		mp2.forceMove(mp2.chooseMove());



		//* Emulated board to test*//

		GameBoard gb3 = new GameBoard(WHITE);
		MachinePlayer mp3 = new MachinePlayer(WHITE);
		mp3.forceMove(new Move(0, 1));
		mp3.opponentMove(new Move(1, 1));
		mp3.forceMove(new Move(0, 2));
		mp3.opponentMove(new Move(1, 3));
		mp3.forceMove(new Move(0, 6));
		mp3.opponentMove(new Move(2, 7));
		mp3.forceMove(new Move(1, 4));
		mp3.opponentMove(new Move(3, 0));
		mp3.forceMove(new Move(2, 1));
		mp3.opponentMove(new Move(3, 3));
		mp3.forceMove(new Move(3, 1));
		mp3.opponentMove(new Move(5, 3));
		mp3.forceMove(new Move(3, 5));
		mp3.opponentMove(new Move(5, 4));
		mp3.forceMove(new Move(5, 2));
		mp3.opponentMove(new Move(5, 6));
		mp3.forceMove(new Move(6, 3));
		mp3.opponentMove(new Move(6, 0));
		mp3.forceMove(new Move(7, 1));



		mp3 = new MachinePlayer(WHITE);
		mp3.forceMove(new Move(0, 1));
		mp3.opponentMove(new Move(1, 1));
		mp3.forceMove(new Move(0, 2));
		mp3.opponentMove(new Move(1, 3));
		mp3.forceMove(new Move(0, 6));
		mp3.opponentMove(new Move(2, 7));
		mp3.forceMove(new Move(1, 4));
		mp3.opponentMove(new Move(3, 0));
		mp3.forceMove(new Move(2, 1));
		mp3.opponentMove(new Move(3, 3));
		mp3.forceMove(new Move(3, 1));
		mp3.opponentMove(new Move(5, 3));
		mp3.forceMove(new Move(3, 5));
		mp3.opponentMove(new Move(5, 4));
		mp3.forceMove(new Move(5, 2));
		mp3.opponentMove(new Move(5, 6));
		mp3.forceMove(new Move(6, 3));
		mp3.opponentMove(new Move(6, 0));
		mp3.forceMove(mp3.chooseMove());



	}
}
